package cn.kgc.util.log;

import cn.kgc.entity.LogsInfo;
import cn.kgc.service.LogsInfoService;
import cn.kgc.util.SpringContextUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * @author wangyue
 * @version 1.0
 */
@Aspect
@Component
@Slf4j
public class LogAdvice {

    /**
     * 找到所有使用LogInfo注解的方法
     */
    @Pointcut("@annotation(cn.kgc.util.log.LogInfo)")
    public void pointcut1() {
    }

    /**
     * 环绕增强
     *
     * @param joinPoint 连接点
     * @return 目标方法的返回值
     */
    @Around("pointcut1()")
    public Object around(ProceedingJoinPoint joinPoint) {
        //获得执行目标方法之前距离1970年1月1日所经过的毫秒数
        long startTime = System.currentTimeMillis();
        try {
            //执行目标方法
            return joinPoint.proceed();
        } catch (Throwable e) {
            //如果目标方法有异常抛出异常信息
            throw new RuntimeException(e);
        } finally {
            //无论目标方法是否有异常都会执行
            long endTime = System.currentTimeMillis();
            //调用保存日志的方法
            saveLog(joinPoint, endTime - startTime);
        }
    }

    @Resource
    private LogsInfoService logsInfoService;

    private void saveLog(ProceedingJoinPoint joinPoint, long time) {
        //执行的目标方法
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        //判断目标方法上是否有LogInfo注解
        if (!method.isAnnotationPresent(LogInfo.class)) {
            //如果目标方法上没有LogInfo注解直接返回
            return;
        }
        //如果目标方法上有LogInfo注解,获得LogInfo注解
        LogInfo logInfoAnnotation = method.getAnnotation(LogInfo.class);
        //系统的操作日志对象
        LogsInfo logsInfo = new LogsInfo();
        logsInfo.setModuleName(logInfoAnnotation.moduleName().getName());
        logsInfo.setDescription(logInfoAnnotation.description());
        logsInfo.setLogType(logInfoAnnotation.logType().getType());
        logsInfo.setUserid(0);
        logsInfo.setCostTime(time);
        logsInfo.setOperateType(logInfoAnnotation.operateType().getCode());
        //获得当前执行的目标方法的类名+方法名
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = className + "类中的:" + method.getName() + "方法";
        logsInfo.setMethod(methodName);
        //获得当前用户访问的接口地址
        HttpServletRequest httpServletRequest = SpringContextUtils.getHttpServletRequest();
        String requestUrl = httpServletRequest.getRequestURL().toString();
        logsInfo.setRequestUrl(requestUrl);
        //保存系统日志
        logsInfoService.save(logsInfo);
    }
}